extends InteractiveObject3D

class_name HingedDoor3D

enum State {OPEN, CLOSED}
enum OpenDirection {CW, CCW}
enum RotationAxis {X, Y, Z}

@export var pivot_point: Node3D
@export var state = State.CLOSED
@export var open_direction = OpenDirection.CW
@export var rotation_axis = RotationAxis.Y

@export var open_angle_limit = 120
@export var rotation_speed = 90

@onready
var cutout_angle = 0

var in_interaction = false

@onready
var openPositionDeg = {
	OpenDirection.CW: -open_angle_limit,
	OpenDirection.CCW: open_angle_limit
}

# Opposite for closing
const rotationOpenDirection = {
	OpenDirection.CW: -1,
	OpenDirection.CCW: 1
}

const rotationAxisMap = {
	RotationAxis.X: 'x',
	RotationAxis.Y: 'y',
	RotationAxis.Z: 'z',
}

func _ready() -> void:
	if state == State.OPEN:
		pivot_point.rotation[rotationAxisMap[rotation_axis]] = deg_to_rad(openPositionDeg[open_direction])
		cutout_angle = openPositionDeg[open_direction]

func _process(delta: float) -> void:
	var direction = rotationOpenDirection[open_direction] * (-1 if state == State.CLOSED else 1)
	if round(rad_to_deg(pivot_point.rotation[rotationAxisMap[rotation_axis]])) != cutout_angle:
		pivot_point.rotation[rotationAxisMap[rotation_axis]] += deg_to_rad(rotation_speed) * direction * delta
	elif in_interaction:
		interaction_end.emit({'state': 1 if state == State.OPEN else -1})
		in_interaction = false
	pivot_point.rotation[rotationAxisMap[rotation_axis]] = clamp(
		pivot_point.rotation[rotationAxisMap[rotation_axis]], 
		deg_to_rad(min(openPositionDeg[open_direction], 0)), 
		deg_to_rad(max(openPositionDeg[open_direction], 0))
		)

func interact(params: Dictionary = {}) -> void:
	state = State.OPEN if state == State.CLOSED else State.CLOSED
	interaction_begin.emit({'state':  1 if state == State.OPEN else -1})
	in_interaction = true
	cutout_angle = rotationOpenDirection[open_direction] * openPositionDeg[state] * (-1 if state == State.OPEN else 0)
